package com.lz.dubbo.consumer.common.utils;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lz.dubbo.consumer.common.exception.base.BaseException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Array;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class SysUtils {
    private static final Logger logger = LoggerFactory.getLogger(SysUtils.class);

    /**
     * 对象转换String  null转换成""
     */
    public static String toString(Object object) {
        return (object == null) ? StringUtils.EMPTY : (object.getClass().isArray() ? ArrayUtil.toString(object)
                : object.toString());
    }

    /**
     * 判断对象是否为空
     */
    public static boolean isVoid(Object obj) {
        if (obj == null) {
            return true;
        } else if ("null".equals(obj)) {
            return true;
        } else if (obj.toString().length() == 0) {
            return true;
        } //去首尾空格
        else if (obj.toString().trim().length() == 0) {
            return true;
        } else if (obj instanceof CharSequence) {
            return ((CharSequence) obj).length() == 0;
        } else if (obj instanceof Collection) {
            return ((Collection) obj).isEmpty();
        } else if (obj instanceof Map) {
            return ((Map) obj).isEmpty();
        } else if (obj.getClass().isArray()) {
            return Array.getLength(obj) == 0;
        } else {
            return false;
        }
    }

    /**
     * 判断对象是否 不为空
     */
    public static boolean isNotVoid(Object obj) {
        return !isVoid(obj);
    }

    /**
     * @return 如果相等, 则返回<code>true</code>
     */
    public static boolean equals(Object object1, Object object2) {
        return ArrayUtil.equals(object1, object2);
    }

    /**
     * 为字符串指定编码 UTF-8
     */
    public static String encode(String str) {
        try {
            str = URLEncoder.encode(str, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    public static String toHex(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    public static byte[] toBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    /*
     * 解码页面传递的字符串 utf-8
     * */
    public static String decode(String str) {
        try {
            str = java.net.URLDecoder.decode(str, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    /*
     * 获取项目路径01
     * */
    public static String getSysPath01() {
        return ClassUtils.getDefaultClassLoader().getResource("").getPath();
    }

    /*
     * 通用下载
     * @param response filePath  fileName
     * */
    public static HttpServletResponse downloadFile(HttpServletResponse response, String filePath, String fileName) {
        FileInputStream input = null;
        OutputStream myout = null;
        try {
            File file = new File(filePath);
            if(!file.exists()){
                throw new BaseException("文件不存在");
            }
            response.setContentType("application/x-msdownload");
            response.setContentLength((int) file.length());
            String fn = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + fn + ";filename*=utf-8''" + fn);
            input = new FileInputStream(file);
            myout = response.getOutputStream();
            IOUtils.copy(input, myout);
            myout.flush();
        } catch (IOException e) {
            throw new BaseException("系统异常，请重试或联系系统管理员！", e.getMessage());
        } finally {
            try {
                if (myout != null) {
                    myout.close();
                }
                if (input != null) {
                    input.close();
                }
            } catch (Exception e) {
            }
        }
        return response;
    }

    /*
     * 为字符串指定编码 UTF-8
     * */
    public static String encodeGBK(String str) {
        try {
            str = URLEncoder.encode(str, "GBK");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return str;
    }

    public static String getErrorMsg(Exception e) {
        String re = e.toString();
        for (int i = 0; i < e.getStackTrace().length; i++) {
            re += e.getStackTrace()[i] + "\n";
        }
        return re;
    }

    public static void deleteFile(File file) {
        //用来判断文件是否删除成功
        int flag = 1;
        //判断文件不为null或文件目录存在
        if (file == null || !file.exists()) {
            flag = 0;
            logger.info("文件删除失败,请检查文件路径是否正确");
            return;
        }
        if (file.isDirectory()) {
            //取得这个目录下的所有子文件对象
            File[] files = file.listFiles();
            //遍历该目录下的文件对象
            for (File f : files) {
                //打印文件名
                String name = file.getName();
                //判断子目录是否存在子目录,如果是文件则删除
                if (f.isDirectory()) {
                    deleteFile(f);
                } else {
                    f.delete();
                }
            }
            //删除空文件夹  for循环已经把上一层节点的目录清空。
            file.delete();

        } else {
            file.delete();
        }
    }

    public static String frontCompWithZore(int formatLength, int formatNumber) {
        /**
         * 0 指前面补充零
         * formatLength 字符总长度为 formatLength
         * inputNumber 格式化数字
         * d 代表为正数。
         */
        String newString = String.format("%0" + formatLength + "d", formatNumber);
        return newString;
    }

    public static boolean isJson(String content) {
        if (StringUtils.isEmpty(content)) {
            return false;
        }
        boolean isJsonObject = true;
        boolean isJsonArray = true;
        try {
            JSONObject.parseObject(content);
        } catch (Exception e) {
            isJsonObject = false;
        }
        try {
            JSON.parseArray(content);
        } catch (Exception e) {
            isJsonArray = false;
        }
        if (!isJsonObject && !isJsonArray) { //不是json格式
            return false;
        }
        return true;
    }

    public static String getFileSize(File file) {
        String size = "";
        if (file.length() >= 1024 * 1024) {
            size = NumberUtil.decimalFormat("######0.00", (double) file.length() / 1024 / 1024) + 'M';
        } else {
            size = NumberUtil.decimalFormat("######0.00", (double) file.length() / 1024) + 'K';
        }
        return size;
    }


    public static void download(HttpServletResponse response,String fileUrl) {
        try {
            File file=new File(fileUrl);
            String filename=file.getName();
            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(fileUrl));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();

            response.setContentType("application/octet-stream;charset=UTF-8");
            String fileName = new String(filename.getBytes("gb2312"), "iso8859-1");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);
            OutputStream ouputStream = response.getOutputStream();
            ouputStream.write(buffer);
            ouputStream.flush();
            ouputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static <T> List<List<T>> getDescartes(List<List<T>> list) {
        List<List<T>> returnList = new ArrayList<>();
        descartesRecursive(list, 0, returnList, new ArrayList<T>());
        return returnList;
    }

    /**
     * 递归实现
     * 原理：从原始list的0开始依次遍历到最后
     *
     * @param originalList 原始list
     * @param position     当前递归在原始list的position
     * @param returnList   返回结果
     * @param cacheList    临时保存的list
     */
    private static <T> void descartesRecursive(List<List<T>> originalList, int position, List<List<T>> returnList, List<T> cacheList) {
        List<T> originalItemList = originalList.get(position);
        for (int i = 0; i < originalItemList.size(); i++) {
            //最后一个复用cacheList，节省内存
            List<T> childCacheList = (i == originalItemList.size() - 1) ? cacheList : new ArrayList<>(cacheList);
            childCacheList.add(originalItemList.get(i));
            if (position == originalList.size() - 1) {//遍历到最后退出递归
                returnList.add(childCacheList);
                continue;
            }
            descartesRecursive(originalList, position + 1, returnList, childCacheList);
        }
    }
}
